package com.atmilan.quartz.service.impl;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.atmilan.quartz.constant.Constants;
import com.atmilan.quartz.constant.enums.ProductTypeEnum;
import com.atmilan.quartz.constant.enums.StockAreaTempEnum;
import com.atmilan.quartz.model.dto.guanjp.GuanjpProductResDTO;
import com.atmilan.quartz.model.dto.guanjp.GuanjpProductResDTO.Ptype;
import com.atmilan.quartz.model.dto.guanjp.GuanjpProductSkuResDTO;
import com.atmilan.quartz.model.entity.crmeb.StoreProduct;
import com.atmilan.quartz.model.entity.crmeb.StoreProductAttrResult;
import com.atmilan.quartz.model.entity.crmeb.StoreProductAttrValue;
import com.atmilan.quartz.model.entity.guanjp.GuanjpProduct;
import com.atmilan.quartz.model.entity.guanjp.GuanjpProductSku;
import com.atmilan.quartz.service.ICategoryMatchService;
import com.atmilan.quartz.service.IGuanjpProductService;
import com.atmilan.quartz.service.IGuanjpProductSkuService;
import com.atmilan.quartz.service.IGuanjpSyncService;
import com.atmilan.quartz.service.IStoreProductAttrResultService;
import com.atmilan.quartz.service.IStoreProductAttrService;
import com.atmilan.quartz.service.IStoreProductAttrValueService;
import com.atmilan.quartz.service.IStoreProductService;
import com.atmilan.quartz.service.ISystemAttachmentService;
import com.atmilan.quartz.service.ISystemConfigService;
import com.atmilan.quartz.utils.RedisUtil;
import com.atmilan.quartz.utils.product.GuanjpProductUtil;
import com.atmilan.quartz.utils.source.SourceGuanjpProductUtil;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service
public class GuanjpSyncServiceImpl implements IGuanjpSyncService {
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private ISystemConfigService systemConfigService;
    @Autowired
    private IGuanjpProductService guanjpProductService;
    @Autowired
    private IGuanjpProductSkuService guanjpProductSkuService;
    @Autowired
    private IStoreProductService storeProductService;
    @Autowired
    private IStoreProductAttrService storeProductAttrService;
    @Autowired
    private IStoreProductAttrValueService storeProductAttrValueService;
    @Autowired
    private  IStoreProductAttrResultService storeProductAttrResultService;
    @Autowired
    private SourceGuanjpProductUtil sourceGuanjpProductUtil;
    @Autowired
    private ICategoryMatchService categoryMatchService;
    @Autowired
    private GuanjpProductUtil guanjpProductUtil;
    
    /**
     * 获取远程数据并保存到数据源
     */
    @Override
    public Boolean syncProduct() {
        // 数据清空
        guanjpProductService.deleteAll();
        guanjpProductSkuService.deleteAll();

        int pageNo = 1;
        int pageCount = 1;
        int pageSize = 20;
        long millis = System.currentTimeMillis();
        String token = guanjpProductUtil.refreshToken();
        while(pageNo <= pageCount) {
            try {
            	// 查询主商品
                GuanjpProductResDTO guanjpProductResDTO = guanjpProductUtil.selectPage(pageNo, pageSize, token);
                List<Ptype> ptypes = guanjpProductResDTO.getResponse().getPtypes();
                List<String> productIds = ptypes.stream().map(obj -> obj.getGoodsId()).collect(Collectors.toList());
                // 通过商品id查询对应商品sku
                GuanjpProductSkuResDTO guanjpProductSkuResDTO = guanjpProductUtil.getSkus(productIds, token);
                List<GuanjpProductSkuResDTO.Goodsstock> goodsstocks = guanjpProductSkuResDTO.getResponse().getGoodsstocks();
                
                // 商品保存
                saveGoods(ptypes, goodsstocks);
                
                // 计算页数
                Integer total = guanjpProductResDTO.getResponse().getTotalresults();
                pageCount = (total + pageSize - 1) / pageSize;
            } catch (Exception e) {
                e.printStackTrace();
            }
            
            log.info("--------------- 管家婆远程抓取数据, 第: {} 页,  总共: {} 页, 总耗时: {} 分, token: {}  ---------------", pageNo, pageCount, (int)((System.currentTimeMillis() - millis) / 1000 / 60), token);
            pageNo++;
        }
    
        return true;
    }
    
    // 商品源数据保存
    private void saveGoods(List<Ptype> goodsList, List<GuanjpProductSkuResDTO.Goodsstock> skuList) {
        // 商品数据
        List<GuanjpProduct> goodsEntity = new ArrayList<>();
        for(Ptype goods : goodsList) {
            GuanjpProduct productEntity = new GuanjpProduct();
            BeanUtils.copyProperties(goods, productEntity);
            productEntity.setCreateTime(new Date());
            goodsEntity.add(productEntity);
        }
        List<GuanjpProductSku> productSkuEntity = new ArrayList<>();
        for(GuanjpProductSkuResDTO.Goodsstock sku : skuList) {
            GuanjpProductSku skuEntity = new GuanjpProductSku();
            BeanUtils.copyProperties(sku, skuEntity);
            skuEntity.setCreateTime(new Date());
            productSkuEntity.add(skuEntity);
        }
        
        guanjpProductService.saveBatch(goodsEntity);
        guanjpProductSkuService.saveBatch(productSkuEntity);
    }

    @Override
    public Boolean pushProduct() {
        try {
            int count = guanjpProductService.count();
            // 商品更新操作
            int pageNo = 1;
            int pageSize = 100;
            int maxPage = (count + pageSize - 1) / pageSize;
            log.info("--------------- 开始分页查询管家婆商品源数据, 本次更新总条数为: {} ---------------", count);

            long millis = System.currentTimeMillis();
            while (pageNo <= maxPage) {
                try {
                    PageHelper.startPage(pageNo, pageSize);
                    List<GuanjpProduct> guanjpProducts = guanjpProductService.list();
                    PageInfo<GuanjpProduct> pageInfo = PageInfo.of(guanjpProducts);
                    List<GuanjpProduct> products = pageInfo.getList();
                    buildProduct(products);
                } catch (Exception e) {
                    e.printStackTrace();
                }

                log.info("--------------- 管家婆下发商品到数据库, 当前页数: {}, 总页数: {}, 耗时: {} 分 ---------------", pageNo, maxPage, (int)((System.currentTimeMillis() - millis) / 1000 / 60));
                pageNo++;
            }

            return true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        
        return false;
    }

    /**
     * 商品构建处理
     * @Description:  
     * @author daigb 
     * @param @param products
     * @return void
     * @throws
     */
    private void buildProduct(List<GuanjpProduct> products) {
        try {
            for (GuanjpProduct product : products) {
            	// 查询sku
                List<GuanjpProductSku> skus = guanjpProductSkuService.list(Wrappers.<GuanjpProductSku>lambdaQuery()
                        .eq(GuanjpProductSku :: getPtypeid, product.getGoodsId())
                        );
                if (CollectionUtils.isEmpty(skus)) {
                    continue;
                }
                // 库存计算
                int stockCN = 0; // 国内仓库存
                int stockHK = 0; // 香港仓库存
                for (GuanjpProductSku sku : skus) {
                	if(GuanjpProductUtil.ktypeidCNs.contains(sku.getKtypeid())) {
                		stockCN += sku.getSaleqty();
                	} else if(GuanjpProductUtil.ktypeidHKs.contains(sku.getKtypeid())) {
                		stockHK += sku.getSaleqty();
                	}
                }

                // 数据保存
                List<StoreProduct> storeProducts = storeProductService.list(Wrappers.<StoreProduct>lambdaQuery()
                		.eq(StoreProduct :: getIsEurope, ProductTypeEnum.XINGFA.getCode())
                		.eq(StoreProduct :: getIsShow, true)
                		.eq(StoreProduct :: getKeyword, product.getBarcode())
                		);
                for(StoreProduct p : storeProducts) {
                	// 默认该供应商都是单sku规格
                	if(StockAreaTempEnum.CN == StockAreaTempEnum.valueOf(p.getTempId())) {
                		updateProduct(p.getId(), product.getPrice(), stockCN);
                	} else if(StockAreaTempEnum.HK == StockAreaTempEnum.valueOf(p.getTempId())) {
                		updateProduct(p.getId(), product.getPrice(), stockHK);
                	}
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    /**
     * 更新商品价格和库存
     * @author daigb
     * @date:  2022-12-16 15:42
     */
    private void updateProduct(Integer id, BigDecimal price, Integer stock) {
    	// 更新主商品
		storeProductService.update(Wrappers.<StoreProduct>lambdaUpdate()
				.eq(StoreProduct :: getId, id)
				.set(StoreProduct :: getPrice, price)
				.set(StoreProduct :: getCost, price)
				.set(StoreProduct :: getSourceCost, price)
				.set(StoreProduct :: getStock, stock)
				);
		// 更新sku
		storeProductAttrValueService.update(Wrappers.<StoreProductAttrValue>lambdaUpdate()
				.eq(StoreProductAttrValue :: getProductId, id)
				.set(StoreProductAttrValue :: getPrice, price)
				.set(StoreProductAttrValue :: getCost, price)
				.set(StoreProductAttrValue :: getSourceCost, price)
				.set(StoreProductAttrValue :: getStock, stock)
				);
		// 更新result表
		StoreProductAttrResult attrResult =  storeProductAttrResultService.getOne(Wrappers.<StoreProductAttrResult>lambdaQuery()
				.eq(StoreProductAttrResult :: getProductId, id)
				.last("LIMIT 1")
				);
		if(null != attrResult) {
			JSONArray newJa = new JSONArray();
			JSONArray ja = JSONArray.parseArray(attrResult.getResult());
			for(int i=0; i<ja.size(); i++) {
				JSONObject result = ja.getJSONObject(i);
				JSONObject jo = new JSONObject();
				jo.put("cost", price);
				jo.put("price", price);
				jo.put("sourceCost", price);
				jo.put("stock", stock);
				jo.put("attrValue", result.get("attrValue"));
				jo.put("barCode", result.get("barCode"));
				jo.put("otPrice", result.get("otPrice"));
				jo.put("productId", result.get("productId"));
				jo.put("image", result.get("image"));
				jo.put("sourceSkuId", result.get("sourceSkuId"));
				jo.put("suk", result.get("suk"));
				newJa.add(jo);
			}
			storeProductAttrResultService.update(Wrappers.<StoreProductAttrResult>lambdaUpdate()
					.eq(StoreProductAttrResult :: getProductId, attrResult.getProductId())
					.set(StoreProductAttrResult :: getResult, newJa.toJSONString())
					);
		}
		
    }
    
}
